#ifndef HUFFMANCOMPRESSOR_H
#define HUFFMANCOMPRESSOR_H

#include <string>
#include <map>
#include <vector>
#include "HuffmanTree.h"

/**
 * @class HuffmanCompressor
 * @brief 实现文件和文件夹的哈夫曼压缩与解压功能。
 *
 * 该类提供了基于哈夫曼编码的文件压缩与解压缩功能，支持文件夹结构的还原，
 * 并允许用户指定文件的输入、输出路径。
 */
class HuffmanCompressor {
public:
    /**
     * @brief 压缩文件或文件夹。
     *
     * 使用哈夫曼编码对指定的文件或文件夹进行压缩，并将结果存储到指定的压缩文件中。
     * @param inputFile 输入文件或文件夹的路径。
     * @param compressedFile 压缩后输出的文件路径。
     */
    void compressFile(const std::string& inputFile, const std::string& compressedFile);
    
    /**
     * @brief 解压缩文件。
     *
     * 根据压缩包内容，解压文件或还原文件夹结构。
     * @param compressedFile 压缩包的路径。
     */
    void decompressFile(const std::string& compressedFile);
    
    /**
     * @brief 设置压缩对象的位置。
     *
     * 指定需要压缩的文件或文件夹路径。
     * @param location 目标文件或文件夹路径。
     */
    void setTargetLocation(const std::string& location);
    
    /**
     * @brief 设置压缩包的位置。
     *
     * 指定压缩后生成的压缩包路径。
     * @param location 压缩包路径。
     */
    void setHuffLocation(const std::string& location);
    
    /**
     * @brief 设置解压后文件的存放位置。
     *
     * 指定解压操作后生成文件或文件夹的存放路径。
     * @param location 解压后文件存放路径。
     */
    void setUnHuffLocation(const std::string& location);

private:
    std::string targetLocation; // 压缩对象的位置
    std::string huffLocation; // 压缩包的位置
    std::string unHuffLocation; // 解压后的位置
    
    /**
     * @brief 统计文件中各字节的频率。
     *
     * 读取指定文件，统计其中每种字节的出现频率。
     * @param inputFile 输入文件路径。
     * @return 一个映射，键为字节，值为其出现的频率。
     */
    std::map<unsigned char, long long> getWeights(const std::string& inputFile);
    
    /**
     * @brief 将二进制字符串转换为单字节字符。
     *
     * 用于将哈夫曼编码的二进制形式转为存储格式。
     * @param binary 二进制字符串。
     * @return 转换后的字节。
     */
    unsigned char binaryStringToChar(const std::string& binary);
    
    /**
     * @brief 将单字节字符转换为二进制字符串。
     *
     * 用于将存储的字符转回哈夫曼编码的二进制形式。
     * @param value 字节值。
     * @return 对应的二进制字符串。
     */
    std::string ucharToBinaryString(unsigned char value);

    /**
     * @brief 遍历文件夹并收集目录和文件信息。
     *
     * 遍历目标文件夹，收集其内部文件和子文件夹的路径信息。
     * @param inputName 文件夹路径。
     * @param filePaths 收集的文件路径列表。
     * @param folderPaths 收集的子文件夹路径列表。
     */
    void collectFolderInfo(const std::string& inputName, std::vector<std::string>& filePaths, std::vector<std::string>& folderPaths);
    
    /**
     * @brief 将文件夹结构信息写入压缩包文件头。
     *
     * 将文件夹及其子文件的信息写入压缩文件，以便解压时还原。
     * @param fout 输出文件流。
     * @param folderName 根目录名称。
     * @param folderPaths 子文件夹路径列表。
     * @param filePaths 文件路径列表。
     */
    void writeFolderMetadata(std::ofstream& fout, std::string folderName, const std::vector<std::string>& folderPaths, const std::vector<std::string>& filePaths);
    
    /**
     * @brief 设置压缩密码。
     *
     * 在压缩包中附加简单的密码保护信息。
     * @param fout 输出文件流。
     */
    void setCompressPassword(std::ofstream& fout);
    
    /**
     * @brief 处理文件覆盖情况。
     *
     * 如果目标路径已存在文件，提示用户是否覆盖。
     * @param fileName 目标文件名。
     * @return 是否允许覆盖，true 表示允许，false 表示拒绝。
     */
    bool askForOverwrite(const std::string& fileName);
};

#endif // HUFFMANCOMPRESSOR_H
